//------------------------------------------------------------------------------------------
//	Copyright and Disclaimer Notice
//
//	Copyright (c) 2013 A.C. Verbeck
//
//	This file is part of dsp_lab: A DSP laboratory
//
//	dsp_lab is free software: you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation, either version 3 of the License, or
//	(at your option) any later version.
//
//	dsp_lab is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU General Public License for more details.
//
//	You should have received a copy of the GNU General Public License
//	along with dsp_lab.  If not, see <http://www.gnu.org/licenses/>.
//
//------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------
//  The mk_mtab utility builds a C structure of frequencies.
//  The index to each frequency is the MIDI number.
//  To output a MIDI note:
//  1) Use the index to select the frequency
//  2) Play the frequency
//------------------------------------------------------------------------------------------

#include <math.h>
#include <stdio.h>
#include <time.h>

#define MIDI_START  0
#define MIDI_END    127
#define OCTAVE_CT   12

#define PI	3.14159265358979323846
#define TAU	6.283185307179586476925286766559

static void header_print(FILE* f);
static void footer_print(FILE* f);
static void octave_init(void);
static void octave_bump(void);
static void octave_print(FILE* f);
static void note_print(FILE* f, double freq, int n_idx, int n);

//------------------------------------------------------------------------------------------
//  Main function:
//  1) declare variables
//  2) Initialize the note, octave and print the declaration
//  3) Loop through all the MIDI notes:
//      if at an octave point, print an octave comment
//      calculate the frequency
//      print the frequency, comment the MIDI note and note name
//  4) Close out the midi_to_pitch array
//------------------------------------------------------------------------------------------
int main()
{
	int note,note_idx;
	double note_freq;
	FILE *fd;

	fd = fopen("mtab.c","w");

	note = 0;
	octave_init();
	header_print(fd);

	for (note_idx=MIDI_START; note_idx<=MIDI_END; note_idx++,note++)  {
		if (note_idx%OCTAVE_CT == 0) {
			octave_print(fd);
			octave_bump();
			note=0;
		}
		note_freq = 220.0 * pow(2.0,((double) note_idx - 57) / 12.0);
		note_print(fd, note_freq, note_idx, note);
	}

	fprintf(fd,"};\n");
	footer_print(fd);
	fclose(fd);
	return 0;
}

//------------------------------------------------------------------------------------------
//  Header functions
//------------------------------------------------------------------------------------------
static void header_print(FILE* f)
{
	time_t      rawtime;
	struct tm*  timeinfo;

	time(&rawtime);
	timeinfo = localtime(&rawtime);

	fprintf(f, "//-------------------------------------------------------------------\n");
	fprintf(f, "//\tmtab.c: MIDI to Frequency table.\n");
	fprintf(f, "//\tTo output a MIDI note:\n");
	fprintf(f, "//\t1) Index this table to select the frequency\n");
	fprintf(f, "//\t2) Play the frequency\n\n");
	fprintf(f, "//\tGeneration Date: %s",asctime (timeinfo));
	fprintf(f, "//\tThis is a generated file.  It is created by mk_mtab program.\n");
	fprintf(f, "//\tDo not edit.\n");
	fprintf(f, "//-------------------------------------------------------------------\n");

	fprintf(f,"\n\ndouble m2p[128] = {");
}

static void footer_print(FILE* f)
{
	fprintf(f,"\n//\n");
	fprintf(f,"//\tEnd: mtab.c\n");
	fprintf(f,"//\n");
}

//------------------------------------------------------------------------------------------
//  Octave functions
//------------------------------------------------------------------------------------------
static int octave = -1;
static void octave_init(void)
{
	octave = -1;
}
static void octave_bump(void)
{
	octave++;
}
static void octave_print(FILE* f)
{
	fprintf(f,"\n//\n");
	fprintf(f,"//\tOctave: %d\n",octave);
	fprintf(f,"//\n");
}

//------------------------------------------------------------------------------------------
//  Note functions
//------------------------------------------------------------------------------------------
static char* n_str[] = {
	"C","C#",
	"D","D#",
	"E",
	"F","F#",
	"G","G#",
	"A","A#",
	"B"
};
static void note_print(FILE* f, double freq, int n_idx, int n)
{
	if (n_idx==MIDI_END)
		fprintf(f, "\t{ %8.2lf,%10.2lf }\t\t\t// Note number: %d (%s)\n",freq,freq*TAU,n_idx,n_str[n]);
	else
		fprintf(f, "\t{ %8.2lf,%10.2lf },\t\t// Note number: %d (%s)\n",freq,freq*TAU,n_idx,n_str[n]);
}

//
//  End: mk_mtab.c
//
